home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Files / Utils / Circular Scrolling.c < prev    next >
Encoding:
Text File  |  2000-10-06  |  48.9 KB  |  1,647 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. //    Circular Scrolling.c
  3. //
  4. //    By:    Vern Jensen
  5. //    
  6. //    Created: 7/20/96
  7. //
  8. //    Description:    Routines that enable you to wrap around while scrolling
  9. //
  10. //    Implementation note: Unlike the standard scrolling engine, Sprites and the visScrollRect
  11. //    in this engine will only hang off the right and bottom edges of the offscreen area when
  12. //    wrapping, not the top and left. This was done to simplify the code in various sections. 
  13. //    It could be done in the standard scrolling engine as well if we want.
  14. //
  15. //    As for how the engine works, it first clips the visScrollRect with the circular world's
  16. //    bounds, wraps each part, and calls a function to draw the sprites in each part. This
  17. //    function clips each sprite with the circular world's bounds, and draws each part,
  18. //    clipping it to the current piece of the visScrollRect it's being drawn in. It may sound
  19. //    complex (and it is!), but it's the only way to do it without running into other problems.
  20. ///--------------------------------------------------------------------------------------
  21.  
  22. #ifndef __QUICKDRAW__
  23. #include <QuickDraw.h>
  24. #endif
  25.  
  26. #ifndef __MEMORY__
  27. #include <Memory.h>
  28. #endif
  29.  
  30. #ifndef __GESTALT__
  31. #include <Gestalt.h>
  32. #endif
  33.  
  34. #ifndef __SPRITEWORLD__
  35. #include <SpriteWorld.h>
  36. #endif
  37.  
  38. #ifndef __SPRITEWORLDUTILS__
  39. #include <SpriteWorldUtils.h>
  40. #endif
  41.  
  42. #ifndef __BLITPIXIEINTERFACE__
  43. #include <BlitPixieInterface.h>
  44. #endif
  45.  
  46. #ifndef __SCROLLING__
  47. #include <Scrolling.h>
  48. #endif
  49.  
  50. #ifndef __TILING__
  51. #include <Tiling.h>
  52. #endif
  53.  
  54. #ifndef __CIRCULARSCROLLING__
  55. #include <Circular Scrolling.h>
  56. #endif
  57.  
  58.  
  59. ///--------------------------------------------------------------------------------------
  60. //    SWUpdateCircularSpriteWorld
  61. ///--------------------------------------------------------------------------------------
  62.  
  63. SW_FUNC void SWUpdateCircularSpriteWorld(
  64.     SpriteWorldPtr spriteWorldP)
  65. {
  66.     GWorldPtr    saveGWorld;
  67.     GDHandle    saveGDH;
  68.     
  69.     SW_ASSERT(spriteWorldP != NULL);
  70.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  71.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  72.     
  73.     GetGWorld( &saveGWorld, &saveGDH );
  74.     
  75.     gSWCurrentSpriteWorld = spriteWorldP;
  76.  
  77.         // Copy the background into the work area
  78.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  79.     (*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
  80.                         spriteWorldP->workFrameP,
  81.                         &spriteWorldP->backFrameP->frameRect,
  82.                         &spriteWorldP->workFrameP->frameRect);
  83.     
  84.     
  85.     spriteWorldP->frameHasOccurred = true;
  86.     SWAnimateCircularSpriteWorld(spriteWorldP);
  87.     
  88.     gSWCurrentSpriteWorld = NULL;
  89.     
  90.     SetGWorld( saveGWorld, saveGDH );
  91. }
  92.  
  93.  
  94. ///--------------------------------------------------------------------------------------
  95. //    SWProcessCircularSpriteWorld
  96. ///--------------------------------------------------------------------------------------
  97.  
  98. SW_FUNC void SWProcessCircularSpriteWorld(
  99.     SpriteWorldPtr spriteWorldP)
  100. {
  101.     register SpriteLayerPtr        curSpriteLayerP;
  102.     register SpritePtr            curSpriteP;
  103.     Rect                        moveBounds = spriteWorldP->scrollRectMoveBounds;
  104.     
  105.         // Process the sprites
  106.     SWProcessSpriteWorld(spriteWorldP);
  107.     if ( !spriteWorldP->frameHasOccurred )
  108.     {
  109.         return;
  110.     }
  111.  
  112.     gSWCurrentSpriteWorld = spriteWorldP;
  113.  
  114.         // Wrap any sprites that have moved outside the scrollRectMoveBounds
  115.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  116.     while (curSpriteLayerP != NULL)
  117.     {
  118.         curSpriteP = curSpriteLayerP->headSpriteP;
  119.  
  120.         while (curSpriteP != NULL)
  121.         {            
  122.                 // Wrap left or right
  123.             if (curSpriteP->destFrameRect.left >= moveBounds.right)
  124.             {
  125.                 curSpriteP->destFrameRect.left -= moveBounds.right;
  126.                 curSpriteP->destFrameRect.right -= moveBounds.right;
  127.             }
  128.             else if (curSpriteP->destFrameRect.left < moveBounds.left)
  129.             {
  130.                 curSpriteP->destFrameRect.left += moveBounds.right;
  131.                 curSpriteP->destFrameRect.right += moveBounds.right;
  132.             }
  133.             
  134.                 // Wrap up or down
  135.             if (curSpriteP->destFrameRect.top >= moveBounds.bottom)
  136.             {
  137.                 curSpriteP->destFrameRect.top -= moveBounds.bottom;
  138.                 curSpriteP->destFrameRect.bottom -= moveBounds.bottom;
  139.             }
  140.             else if (curSpriteP->destFrameRect.top < moveBounds.top)
  141.             {
  142.                 curSpriteP->destFrameRect.top += moveBounds.bottom;
  143.                 curSpriteP->destFrameRect.bottom += moveBounds.bottom;
  144.             }
  145.             
  146.             curSpriteP = curSpriteP->nextSpriteP;
  147.         }
  148.         
  149.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  150.     }
  151.     
  152.     
  153.         // Call the scrolling world move proc
  154.     if (spriteWorldP->worldMoveProc != NULL)
  155.     {
  156.         (*spriteWorldP->worldMoveProc)(spriteWorldP, spriteWorldP->followSpriteP);
  157.     }
  158.     
  159.     
  160.         // Move visScrollRect
  161.     if (spriteWorldP->horizScrollDelta || spriteWorldP->vertScrollDelta)
  162.     {
  163.         SWOffsetCircularVisScrollRect(spriteWorldP, 
  164.             spriteWorldP->horizScrollDelta, 
  165.             spriteWorldP->vertScrollDelta);
  166.     }
  167.     
  168.         // Process any Sprites in a non-scrolling SpriteLayer
  169.     SWProcessNonScrollingLayers(spriteWorldP);
  170.     
  171.     gSWCurrentSpriteWorld = NULL;
  172. }
  173.  
  174.  
  175.     // Variables shared by SWAnimateCircularSpriteWorld and SWErasePieceOfSprite.
  176.     // These keep track of the vert and horiz scroll rect offset from the previous frame.
  177. short    gOldVertScrollRectOffset, gOldHorizScrollRectOffset;
  178.  
  179.     // Variables shared by SWAnimateCircularSpriteWorld and SWDrawTilesInWrappedRect.
  180.     // These store the original values of the named variables, so the named variables can
  181.     // temporarily be changed and restored.
  182. short    gTempHorizScrollRectOffset, gTempVertScrollRectOffset;
  183. short    gTempOldVertScrollRectOffset, gTempOldHorizScrollRectOffset;
  184.  
  185.  
  186. ///--------------------------------------------------------------------------------------
  187. //    SWAnimateCircularSpriteWorld
  188. ///--------------------------------------------------------------------------------------
  189.  
  190. SW_FUNC void SWAnimateCircularSpriteWorld(
  191.     SpriteWorldPtr spriteWorldP)
  192. {
  193.     UpdateRectStructPtr            curRectStructP,
  194.                                 nextRectStructP;
  195.     register SpriteLayerPtr     curSpriteLayerP;
  196.     register SpritePtr             curSpriteP;
  197.     Rect                        *moveBounds = &spriteWorldP->scrollRectMoveBounds;
  198.     Rect                        rectA, rectB, rectC, rectD, tempDstRect;
  199.     Boolean                        horizClip, vertClip;
  200.  
  201.     SW_ASSERT(spriteWorldP != NULL);
  202.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  203.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  204.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  205.     
  206.     if (!spriteWorldP->frameHasOccurred)
  207.         return;
  208.     
  209.     gSWCurrentSpriteWorld = spriteWorldP;
  210.     
  211.         // Add the deadSpriteLayer if there are any Sprites in it.
  212.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  213.     {
  214.         SWAddSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  215.     }
  216.     
  217.     
  218.     gOldVertScrollRectOffset = spriteWorldP->backRect.bottom * 
  219.         (spriteWorldP->oldVisScrollRect.top / spriteWorldP->backRect.bottom);
  220.     
  221.     gOldHorizScrollRectOffset = spriteWorldP->backRect.right *
  222.         (spriteWorldP->oldVisScrollRect.left / spriteWorldP->backRect.right);
  223.     
  224.     gTempHorizScrollRectOffset = spriteWorldP->horizScrollRectOffset;
  225.     gTempVertScrollRectOffset = spriteWorldP->vertScrollRectOffset;
  226.     gTempOldVertScrollRectOffset = gOldVertScrollRectOffset;
  227.     gTempOldHorizScrollRectOffset = gOldHorizScrollRectOffset;
  228.  
  229.  
  230.         // Set the port to the work area so we can draw in it
  231.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  232.     
  233.     
  234.         // Update the tiles as we scroll
  235.     SWDrawTilesInCircularScrollRect(spriteWorldP);
  236.  
  237.  
  238.     //-----------------erase the sprites--------------------
  239.     
  240.     rectA = spriteWorldP->oldVisScrollRect;
  241.     
  242.         // Wrap right side to the left
  243.     if (rectA.right > moveBounds->right)
  244.     {
  245.         rectB.top = rectA.top;
  246.         rectB.bottom = rectA.bottom;
  247.         rectB.left = moveBounds->left;
  248.         rectB.right = rectA.right - moveBounds->right;
  249.         
  250.         rectA.right = moveBounds->right;
  251.         horizClip = true;
  252.     }
  253.     else
  254.         horizClip = false;
  255.     
  256.     
  257.         // Wrap bottom side to the top
  258.     if (rectA.bottom > moveBounds->bottom)
  259.     {
  260.         rectC.left = rectA.left;
  261.         rectC.right = rectA.right;
  262.         rectC.top = moveBounds->top;
  263.         rectC.bottom = rectA.bottom - moveBounds->bottom;
  264.         
  265.         rectA.bottom = moveBounds->bottom;
  266.         rectB.bottom = moveBounds->bottom;;
  267.         vertClip = true;
  268.     }
  269.     else
  270.         vertClip = false;
  271.         
  272.         
  273.     SWEraseSpritesInRect(spriteWorldP, &rectA);
  274.     
  275.     if (horizClip)
  276.     {
  277.         gOldHorizScrollRectOffset = 0;  // Draw the sprites at the left of the world
  278.         SWEraseSpritesInRect(spriteWorldP, &rectB);
  279.         gOldHorizScrollRectOffset = gTempOldHorizScrollRectOffset;
  280.     }
  281.     
  282.     if (vertClip)
  283.     { 
  284.         gOldVertScrollRectOffset = 0;    // Draw the sprites at the top of the world
  285.         SWEraseSpritesInRect(spriteWorldP, &rectC);
  286.         gOldVertScrollRectOffset = gTempOldVertScrollRectOffset;
  287.     }
  288.     
  289.         // Wrap the corner piece
  290.     if (vertClip && horizClip)
  291.     {
  292.         rectD.left = rectB.left;
  293.         rectD.right = rectB.right;
  294.         rectD.top = rectC.top;
  295.         rectD.bottom = rectC.bottom;
  296.          
  297.         gOldVertScrollRectOffset = 0;        // Draw the sprites at the top of the world
  298.         gOldHorizScrollRectOffset = 0;        // Draw the sprites at the left of the world
  299.         
  300.         SWEraseSpritesInRect(spriteWorldP, &rectD);
  301.  
  302.         gOldHorizScrollRectOffset = gTempOldHorizScrollRectOffset;
  303.         gOldVertScrollRectOffset = gTempOldVertScrollRectOffset;
  304.     }
  305.     
  306.     
  307.         // update flagged background rects
  308.     curRectStructP = spriteWorldP->headUpdateRectP;
  309.     while ( curRectStructP != NULL )
  310.     {
  311.         tempDstRect = curRectStructP->updateRect;
  312.         
  313.             // Make the rect local to the offscreen area
  314.         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  315.         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  316.         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  317.         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  318.         
  319.             // We're not really erasing a sprite, just copying while wrapping
  320.         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  321.         curRectStructP = curRectStructP->nextRectStructP;
  322.     }
  323.     
  324.         // Call the postEraseCallBack
  325.     if (spriteWorldP->postEraseCallBack != NULL)
  326.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  327.  
  328.     
  329.     
  330.     //-----------------draw the sprites-------------------
  331.     
  332.     rectA = spriteWorldP->visScrollRect;
  333.     
  334.         // wrap right side to the left
  335.     if (rectA.right > moveBounds->right)
  336.     {
  337.         rectB.top = rectA.top;
  338.         rectB.bottom = rectA.bottom;
  339.         rectB.left = moveBounds->left;
  340.         rectB.right = rectA.right - moveBounds->right;
  341.         
  342.         rectA.right = moveBounds->right;
  343.         horizClip = true;
  344.     }
  345.     else
  346.         horizClip = false;
  347.     
  348.     
  349.         // Wrap bottom side to the top
  350.     if (rectA.bottom > moveBounds->bottom)
  351.     {
  352.         rectC.left = rectA.left;
  353.         rectC.right = rectA.right;
  354.         rectC.top = moveBounds->top;
  355.         rectC.bottom = rectA.bottom - moveBounds->bottom;
  356.         
  357.         rectA.bottom = moveBounds->bottom;
  358.         rectB.bottom = moveBounds->bottom;
  359.         vertClip = true;
  360.     }
  361.     else
  362.         vertClip = false;
  363.     
  364.     
  365.     SWDrawSpritesInRect(spriteWorldP, &rectA);
  366.     
  367.     if (horizClip)
  368.     {
  369.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the sprites at the left of the world
  370.         SWDrawSpritesInRect(spriteWorldP, &rectB);
  371.         spriteWorldP->horizScrollRectOffset = gTempHorizScrollRectOffset;
  372.     }
  373.     
  374.     if (vertClip)
  375.     {
  376.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the sprites at the top of the world
  377.         SWDrawSpritesInRect(spriteWorldP, &rectC);
  378.         spriteWorldP->vertScrollRectOffset = gTempVertScrollRectOffset;
  379.     }
  380.     
  381.         // Wrap the corner piece
  382.     if (vertClip && horizClip)
  383.     {
  384.         rectD.left = rectB.left;
  385.         rectD.right = rectB.right;
  386.         rectD.top = rectC.top;
  387.         rectD.bottom = rectC.bottom;
  388.         
  389.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the sprites at the left of the world
  390.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the sprites at the top of the world
  391.         
  392.         SWDrawSpritesInRect(spriteWorldP, &rectD);
  393.         
  394.         spriteWorldP->vertScrollRectOffset = gTempVertScrollRectOffset;
  395.         spriteWorldP->horizScrollRectOffset = gTempHorizScrollRectOffset;
  396.     }
  397.     
  398.     
  399.         // Clean up //
  400.         
  401.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  402.  
  403.         // iterate through the layers in this world
  404.     while (curSpriteLayerP != NULL)
  405.     {
  406.         curSpriteP = curSpriteLayerP->headSpriteP;
  407.  
  408.             // iterate through the sprites in this layer
  409.         while (curSpriteP != NULL)
  410.         {
  411.                 // Set last rect to current rect
  412.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  413.             
  414.             curSpriteP->needsToBeDrawn = false;
  415.             curSpriteP->needsToBeErased = false;
  416.  
  417.             curSpriteP = curSpriteP->nextSpriteP;
  418.         }
  419.         
  420.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  421.     }
  422.     
  423.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  424.     
  425.     
  426.         // Call the postDrawCallBack
  427.     if (spriteWorldP->postDrawCallBack != NULL)
  428.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  429.     
  430.     
  431.     //-----------------update the screen--------------------
  432.     
  433.         // Set the port to the window
  434.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  435.     
  436.     if (spriteWorldP->usingVBL)
  437.     {  
  438.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  439.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  440.         {}
  441.     }
  442.     
  443.         // Copy offscreen area to screen while wrapping
  444.     SWWrapWorkAreaToFrame(spriteWorldP, spriteWorldP->windowFrameP, &spriteWorldP->windRect);
  445.     
  446.     
  447.         // dispose of flagged background rects
  448.     nextRectStructP = spriteWorldP->headUpdateRectP;
  449.     while ( nextRectStructP != NULL )
  450.     {
  451.         curRectStructP = nextRectStructP;
  452.         nextRectStructP = curRectStructP->nextRectStructP;
  453.         DisposePtr( (Ptr)curRectStructP );
  454.     }
  455.     spriteWorldP->headUpdateRectP = NULL;
  456.     
  457.     spriteWorldP->numTilesChanged = 0;
  458.     
  459.     
  460.         // Remove the deadSpriteLayer if we added it earlier.
  461.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  462.     {
  463.         SWRemoveSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  464.     }
  465.     
  466.     gSWCurrentSpriteWorld = NULL;
  467. }
  468.  
  469.  
  470. #pragma mark -
  471. ///--------------------------------------------------------------------------------------
  472. //  SWDrawTilesInCircularScrollRect - called by SWAnimateCircularSpriteWorld to update
  473. //    the portion of the visScrollRect that just scrolled into view.
  474. ///--------------------------------------------------------------------------------------
  475.  
  476. void SWDrawTilesInCircularScrollRect(
  477.     SpriteWorldPtr    spriteWorldP)
  478. {
  479.     Rect        tempDstRect;
  480.     short        distA, distB;
  481.     short        hScrollDelta, vScrollDelta;
  482.     
  483.         // Calculate the scrollDelta of the visScrollRect. Since it maybe have
  484.         // wrapped around since the previous frame, we must go through some extra
  485.         // hoops to make sure we calculate the delta correctly.
  486.     distA = spriteWorldP->visScrollRect.left - spriteWorldP->oldVisScrollRect.left;
  487.     if (distA < 0)    // if (visScrollRect.left < oldVisScrollRect.left)
  488.         distB = distA + spriteWorldP->scrollRectMoveBounds.right;
  489.     else
  490.         distB = distA - spriteWorldP->scrollRectMoveBounds.right;
  491.     
  492.     if ( SW_ABS(distB) < SW_ABS(distA) )
  493.         hScrollDelta = distB;
  494.     else
  495.         hScrollDelta = distA;
  496.     
  497.         // Do the same for the vScrollDelta...
  498.     distA = spriteWorldP->visScrollRect.top - spriteWorldP->oldVisScrollRect.top;
  499.     if (distA < 0)    // if (visScrollRect.top < oldVisScrollRect.top)
  500.         distB = distA + spriteWorldP->scrollRectMoveBounds.bottom;
  501.     else
  502.         distB = distA - spriteWorldP->scrollRectMoveBounds.bottom;
  503.     
  504.     if ( SW_ABS(distB) < SW_ABS(distA) )
  505.         vScrollDelta = distB;
  506.     else
  507.         vScrollDelta = distA;
  508.     
  509.     
  510.         // Update tiles as we scroll if tiling is turned on
  511.     if (spriteWorldP->tilingIsOn)
  512.     {
  513.             // VisScrollRect moved horizontally
  514.         if (hScrollDelta)
  515.         {
  516.                 // Get rect of new vertical section to update
  517.             tempDstRect = spriteWorldP->visScrollRect;
  518.                 
  519.             if (hScrollDelta < 0)
  520.                 tempDstRect.right = tempDstRect.left - hScrollDelta;    // Moved left
  521.             else    
  522.                 tempDstRect.left = tempDstRect.right - hScrollDelta;    // Moved right
  523.     
  524.             SWDrawTilesInWrappedRect(spriteWorldP, &tempDstRect, true);
  525.             
  526.             
  527.                 // Did VisScrollRect moved diagonally?
  528.             if (vScrollDelta)
  529.             {
  530.                     // Get rect of new horizontal section to update
  531.                 tempDstRect = spriteWorldP->visScrollRect;
  532.                 
  533.                 if (vScrollDelta < 0)
  534.                     tempDstRect.bottom = tempDstRect.top - vScrollDelta;    // Moved up
  535.                 else    
  536.                     tempDstRect.top = tempDstRect.bottom - vScrollDelta;    // Moved down
  537.                 
  538.                     // Clip off the part we've already updated
  539.                 if (hScrollDelta < 0)
  540.                     tempDstRect.left -= hScrollDelta;
  541.                 else    
  542.                     tempDstRect.right -= hScrollDelta;
  543.                 
  544.                     // We pass false here to avoid a bug which occured in the
  545.                     // tile optimizing code when updating tiles twice in one frame
  546.                 if (tempDstRect.right > tempDstRect.left)
  547.                 {
  548.                     SWDrawTilesInWrappedRect(spriteWorldP, &tempDstRect, false);
  549.                 }
  550.             }
  551.         }    // VisScrollRect moved vertically only (not diagonally)
  552.         else if (vScrollDelta)
  553.         {
  554.                 // Get rect of new horizontal section to update
  555.             tempDstRect = spriteWorldP->visScrollRect;
  556.             
  557.             if (vScrollDelta < 0)
  558.                 tempDstRect.bottom = tempDstRect.top - vScrollDelta;    // Moved up
  559.             else    
  560.                 tempDstRect.top = tempDstRect.bottom - vScrollDelta;    // Moved down
  561.  
  562.             SWDrawTilesInWrappedRect(spriteWorldP, &tempDstRect, true);
  563.         }
  564.     }
  565. }
  566.  
  567. ///--------------------------------------------------------------------------------------
  568. //  SWDrawTilesInWrappedRect - called by SWDrawTilesInCircularScrollRect. This function
  569. //    draws the tiles in the rect, while wrapping the rect around the circular world's
  570. //    bounds if it is hanging off the edge of the circular world.
  571. ///--------------------------------------------------------------------------------------
  572.  
  573. void SWDrawTilesInWrappedRect(
  574.     SpriteWorldPtr    spriteWorldP,
  575.     Rect*            tempDstRectP,
  576.     Boolean            optimizingMode)
  577. {
  578.     Rect*        backRectP = &spriteWorldP->scrollRectMoveBounds;
  579.     Rect        rectA, rectB, rectC, rectD;
  580.     Boolean        horizClip, vertClip;
  581.     
  582.     
  583.     rectA = *tempDstRectP;
  584.  
  585.     
  586.         // Clip and wrap left or right side
  587.     if (rectA.right > backRectP->right)
  588.     {
  589.             // wrap right side to the left
  590.         rectB = rectA;
  591.         
  592.         if (rectB.left < backRectP->right)
  593.             rectB.left = backRectP->right;
  594.         
  595.         rectB.left -= backRectP->right;
  596.         rectB.right -= backRectP->right;
  597.         
  598.         rectA.right = backRectP->right;
  599.         horizClip = true;
  600.     }
  601.     else
  602.         horizClip = false;
  603.     
  604.     
  605.     if (rectA.bottom > backRectP->bottom)
  606.     {
  607.             // wrap bottom side to the top
  608.         rectC = rectA;
  609.  
  610.         if (rectC.top < backRectP->bottom)
  611.             rectC.top = backRectP->bottom;
  612.         
  613.         rectC.top -= backRectP->bottom;
  614.         rectC.bottom -= backRectP->bottom;
  615.         
  616.         rectA.bottom = backRectP->bottom;
  617.         rectB.bottom = backRectP->bottom;
  618.         vertClip = true;
  619.     }
  620.     else
  621.         vertClip = false;
  622.     
  623.     
  624.     if ( (rectA.bottom > rectA.top) && (rectA.right > rectA.left) )
  625.     {
  626.         (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectA, optimizingMode);
  627.         SWWrapRectToWorkArea(spriteWorldP, &rectA);
  628.     }
  629.     
  630.     if (horizClip)
  631.     {
  632.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the tiles at the left of the world
  633.         
  634.         if ( (rectB.bottom > rectB.top) && (rectB.right > rectB.left) )
  635.         {
  636.             (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectB, optimizingMode);
  637.             SWWrapRectToWorkArea(spriteWorldP, &rectB);
  638.         }
  639.         
  640.         spriteWorldP->horizScrollRectOffset = gTempHorizScrollRectOffset;
  641.     }
  642.     
  643.     if (vertClip)
  644.     {
  645.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the tiles at the top of the world
  646.         
  647.         if ( (rectC.bottom > rectC.top) && (rectC.right > rectC.left) )
  648.         {
  649.             (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectC, optimizingMode);
  650.             SWWrapRectToWorkArea(spriteWorldP, &rectC);
  651.         }
  652.         
  653.         spriteWorldP->vertScrollRectOffset = gTempVertScrollRectOffset;
  654.     }
  655.  
  656.         // Wrap the corner piece
  657.     if (vertClip && horizClip)
  658.     {
  659.         rectD.left = rectB.left;
  660.         rectD.right = rectB.right;
  661.         rectD.top = rectC.top;
  662.         rectD.bottom = rectC.bottom;
  663.         
  664.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the tiles at the left of the world
  665.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the tiles at the top of the world
  666.         
  667.         if ( (rectD.bottom > rectD.top) && (rectD.right > rectD.left) )
  668.         {
  669.             (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectD, optimizingMode);
  670.             SWWrapRectToWorkArea(spriteWorldP, &rectD);
  671.         }
  672.         
  673.         spriteWorldP->vertScrollRectOffset = gTempVertScrollRectOffset;
  674.         spriteWorldP->horizScrollRectOffset = gTempHorizScrollRectOffset;
  675.     }
  676. }
  677.     
  678.  
  679. ///--------------------------------------------------------------------------------------
  680. //  SWEraseSpritesInRect - this is called up to four times by SWAnimateCircularSpriteWorld,
  681. //    since that function clips the visScrollRect with the scrollingWorldMoveBounds.
  682. //    Whenever that rectangle is clipped, the sprites are erased in each piece. This is
  683. //    what allows the sprites to wrap around the world, even when they're half on one side
  684. //    of the world and half on another side.
  685. //
  686. //    This function also handles the drawing of tiles in the updateRect as we scroll.
  687. ///--------------------------------------------------------------------------------------
  688.  
  689. void SWEraseSpritesInRect(
  690.     SpriteWorldPtr    spriteWorldP,
  691.     Rect*            updateRectP)
  692. {
  693.     register SpriteLayerPtr     curSpriteLayerP;
  694.     register SpritePtr             curSpriteP;
  695.     short                        curTileLayer;
  696.     Rect                        dstRectA, dstRectB, dstRectC, dstRectD;
  697.     short                        rightClip, bottomClip;
  698.     
  699.     
  700.     //-----------------erase the sprites--------------------
  701.     
  702.     
  703.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  704.     curTileLayer = 0;
  705.  
  706.         // iterate through the layers in this world
  707.     while (curSpriteLayerP != NULL)
  708.     {
  709.         curSpriteP = curSpriteLayerP->headSpriteP;
  710.         
  711.         if (curSpriteLayerP->tileLayer > curTileLayer)
  712.             curTileLayer = curSpriteLayerP->tileLayer;
  713.  
  714.             // iterate through the sprites in this layer
  715.         while (curSpriteP != NULL)
  716.         {
  717.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  718.             curSpriteP->tileDepth = curTileLayer;
  719.             
  720.             if (curSpriteP->isVisible)
  721.             {
  722.                 dstRectA = curSpriteP->oldFrameRect;
  723.                 
  724.                 // Here we clip the sprite with the circular world's right and bottom sides. 
  725.                 // Then we clip each piece with the updateRectP and draw it.
  726.  
  727.                     // clip off the bottom
  728.                 if (dstRectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
  729.                 {
  730.                     bottomClip = dstRectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
  731.                     dstRectA.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  732.                 }
  733.                 else
  734.                     bottomClip = 0;
  735.                 
  736.                     // clip off the right
  737.                 if (dstRectA.right > spriteWorldP->scrollRectMoveBounds.right)
  738.                 {
  739.                     rightClip = dstRectA.right - spriteWorldP->scrollRectMoveBounds.right;
  740.                     dstRectA.right = spriteWorldP->scrollRectMoveBounds.right;
  741.                 }
  742.                 else
  743.                     rightClip = 0;
  744.                 
  745.                 
  746.                     // First erase the main piece of the sprite
  747.                 SWErasePieceOfSprite(spriteWorldP, updateRectP, &dstRectA);
  748.  
  749.                 if (bottomClip)    // Wrap bottom piece to top
  750.                 {
  751.                     dstRectB.right = dstRectA.right;
  752.                     dstRectB.left = dstRectA.left;
  753.                     dstRectB.top = spriteWorldP->scrollRectMoveBounds.top;
  754.                     dstRectB.bottom = spriteWorldP->scrollRectMoveBounds.top + bottomClip;
  755.                     
  756.                     SWErasePieceOfSprite(spriteWorldP, updateRectP, &dstRectB);
  757.                 }
  758.                 
  759.                 if (rightClip)        // Wrap right piece to the left
  760.                 {
  761.                     dstRectC.top = dstRectA.top;
  762.                     dstRectC.bottom = dstRectA.bottom;
  763.                     dstRectC.left = spriteWorldP->scrollRectMoveBounds.left;
  764.                     dstRectC.right = spriteWorldP->scrollRectMoveBounds.left + rightClip;
  765.                     
  766.                     SWErasePieceOfSprite(spriteWorldP, updateRectP, &dstRectC);
  767.                 }
  768.                 
  769.                     // If there is a corner piece, wrap it too.
  770.                 if (rightClip && bottomClip)
  771.                 {
  772.                     dstRectD.top = dstRectB.top;
  773.                     dstRectD.bottom = dstRectB.bottom;
  774.                     dstRectD.left = dstRectC.left;
  775.                     dstRectD.right = dstRectC.right;
  776.                     
  777.                     SWErasePieceOfSprite(spriteWorldP, updateRectP, &dstRectD);
  778.                 }
  779.             }
  780.             
  781.             curSpriteP = curSpriteP->nextSpriteP;
  782.         }
  783.         
  784.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  785.     }
  786. }
  787.  
  788.  
  789. ///--------------------------------------------------------------------------------------
  790. //  SWDrawSpritesInRect - this is called up to four times by SWAnimateCircularSpriteWorld,
  791. //    since that function clips the visScrollRect with the scrollingWorldMoveBounds.
  792. //    Whenever that rectangle is clipped, the sprites are drawn in each piece. This is
  793. //    what allows the sprites to wrap around the world, even when they're half on one side
  794. //    of the world and half on another side.
  795. ///--------------------------------------------------------------------------------------
  796.  
  797. void SWDrawSpritesInRect(
  798.     SpriteWorldPtr    spriteWorldP,
  799.     Rect*            updateRectP)
  800. {
  801.     register SpriteLayerPtr     curSpriteLayerP;
  802.     register SpritePtr             curSpriteP;
  803.     Rect                        srcRectA, srcRectB, srcRectC, srcRectD;
  804.     Rect                        dstRectA, dstRectB, dstRectC, dstRectD;
  805.     short                        rightClip, bottomClip;
  806.  
  807.     
  808.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  809.  
  810.         // iterate through the layers in this world
  811.     while (curSpriteLayerP != NULL)
  812.     {
  813.         curSpriteP = curSpriteLayerP->headSpriteP;
  814.  
  815.             // iterate through the sprites in this layer
  816.         while (curSpriteP != NULL)
  817.         {
  818.             if (curSpriteP->isVisible)
  819.             {
  820.                 srcRectA = curSpriteP->curFrameP->frameRect;
  821.                 dstRectA = curSpriteP->destFrameRect;
  822.                 
  823.                     // Here we clip the sprite with the circular world's bounds. Then
  824.                     // we clip each piece with the updateRectP and draw it.
  825.                 
  826.                     // clip off the bottom
  827.                 if (dstRectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
  828.                 {
  829.                     bottomClip = dstRectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
  830.                     dstRectA.bottom -= bottomClip;
  831.                     srcRectA.bottom -= bottomClip;
  832.                 }
  833.                 else
  834.                     bottomClip = 0;
  835.                 
  836.                     // clip off the right
  837.                 if (dstRectA.right > spriteWorldP->scrollRectMoveBounds.right)
  838.                 {
  839.                     rightClip = dstRectA.right - spriteWorldP->scrollRectMoveBounds.right;
  840.                     dstRectA.right -= rightClip;
  841.                     srcRectA.right -= rightClip;
  842.                 }
  843.                 else
  844.                     rightClip = 0;
  845.                 
  846.                     // First draw the main piece of the sprite
  847.                 SWDrawPieceOfSprite(spriteWorldP, updateRectP, curSpriteP, 
  848.                         &srcRectA, &dstRectA);
  849.                 
  850.                     // Now we wrap any pieces that are hanging off the border of
  851.                     // the circular scrolling world. (Which were clipped above.)
  852.  
  853.                 if (bottomClip)        // Wrap bottom piece to top
  854.                 {
  855.                     dstRectB.right = dstRectA.right;
  856.                     dstRectB.left = dstRectA.left;
  857.                     dstRectB.top = spriteWorldP->scrollRectMoveBounds.top;
  858.                     dstRectB.bottom = spriteWorldP->scrollRectMoveBounds.top + bottomClip;
  859.                     
  860.                     srcRectB = srcRectA;
  861.                     srcRectB.bottom += bottomClip; 
  862.                     srcRectB.top += SW_RECT_HEIGHT(dstRectA);
  863.                     
  864.                     SWDrawPieceOfSprite(spriteWorldP, updateRectP, curSpriteP, 
  865.                         &srcRectB, &dstRectB);
  866.                 }
  867.                 
  868.                 if (rightClip)        // Wrap right piece to the left
  869.                 {
  870.                     dstRectC.top = dstRectA.top;
  871.                     dstRectC.bottom = dstRectA.bottom;
  872.                     dstRectC.left = spriteWorldP->scrollRectMoveBounds.left;
  873.                     dstRectC.right = spriteWorldP->scrollRectMoveBounds.left + rightClip;
  874.                     
  875.                     srcRectC = srcRectA;
  876.                     srcRectC.right += rightClip; 
  877.                     srcRectC.left += SW_RECT_WIDTH(dstRectA);
  878.                     
  879.                     SWDrawPieceOfSprite(spriteWorldP, updateRectP, curSpriteP, 
  880.                         &srcRectC, &dstRectC);
  881.                 }
  882.                 
  883.                     // If there is a corner piece, wrap it too.
  884.                 if (rightClip && bottomClip)
  885.                 {
  886.                     dstRectD.top = dstRectB.top;
  887.                     dstRectD.bottom = dstRectB.bottom;
  888.                     dstRectD.left = dstRectC.left;
  889.                     dstRectD.right = dstRectC.right;
  890.                     
  891.                     srcRectD.top = srcRectB.top;
  892.                     srcRectD.bottom = srcRectB.bottom;
  893.                     srcRectD.left = srcRectC.left;
  894.                     srcRectD.right = srcRectC.right;
  895.                     
  896.                     SWDrawPieceOfSprite(spriteWorldP, updateRectP, curSpriteP, 
  897.                         &srcRectD, &dstRectD);
  898.                 }
  899.             }
  900.             
  901.             curSpriteP = curSpriteP->nextSpriteP;
  902.         }
  903.         
  904.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  905.     }
  906. }
  907.  
  908.  
  909. ///--------------------------------------------------------------------------------------
  910. //  SWErasePieceOfSprite
  911. ///--------------------------------------------------------------------------------------
  912.                 
  913. void SWErasePieceOfSprite(
  914.     SpriteWorldPtr    spriteWorldP,
  915.     Rect*            updateRectP,
  916.     Rect*            dstRectP)
  917. {
  918.     Rect    dstRect = *dstRectP;
  919.     short    temp;
  920.     
  921.         // Clip the sprite with this portion of the visScrollRect
  922.     if (dstRect.top < updateRectP->top)
  923.         dstRect.top = updateRectP->top;
  924.     
  925.     if (dstRect.bottom > updateRectP->bottom)
  926.         dstRect.bottom = updateRectP->bottom;
  927.     
  928.     if (dstRect.left < updateRectP->left)
  929.         dstRect.left = updateRectP->left;
  930.     
  931.     if (dstRect.right > updateRectP->right)
  932.         dstRect.right = updateRectP->right;
  933.     
  934.     
  935.         // Is the sprite visible in this rect?
  936.     if ( (dstRect.right > dstRect.left) && (dstRect.bottom > dstRect.top) )
  937.     {
  938.             // Make the sprite's rect local to the offscreen area
  939.         dstRect.top -= gOldVertScrollRectOffset;
  940.         dstRect.bottom -= gOldVertScrollRectOffset;
  941.         dstRect.left -= gOldHorizScrollRectOffset;
  942.         dstRect.right -= gOldHorizScrollRectOffset;
  943.         
  944.             // align the left edge to long word boundary
  945.         dstRect.left &= (spriteWorldP->workFrameP->leftAlignFactor);
  946.         
  947.             // align the right edge to long word boundary
  948.         temp = dstRect.right & spriteWorldP->workFrameP->rightAlignFactor;
  949.             
  950.         if (temp != 0)
  951.             dstRect.right += (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  952.         
  953.         SWEraseWrappedSprite(spriteWorldP, &dstRect);
  954.     }
  955. }
  956.  
  957.  
  958. ///--------------------------------------------------------------------------------------
  959. //  SWDrawPieceOfSprite
  960. ///--------------------------------------------------------------------------------------
  961.                 
  962. void SWDrawPieceOfSprite(
  963.     SpriteWorldPtr    spriteWorldP,
  964.     Rect*            updateRectP,
  965.     SpritePtr        curSpriteP,
  966.     Rect*            srcRectP,
  967.     Rect*            dstRectP)
  968. {
  969.     Rect    srcRect = *srcRectP;
  970.     Rect    dstRect = *dstRectP;
  971.     Rect    tempDstRect;
  972.     
  973.         // Clip the sprite with this portion of the visScrollRect
  974.     if (dstRect.top < updateRectP->top)
  975.     {
  976.         srcRect.top += updateRectP->top - dstRect.top;
  977.         dstRect.top = updateRectP->top;
  978.     }
  979.     
  980.     if (dstRect.bottom > updateRectP->bottom)
  981.     {
  982.         srcRect.bottom += updateRectP->bottom - dstRect.bottom;
  983.         dstRect.bottom = updateRectP->bottom;
  984.     }
  985.     
  986.     if (dstRect.left < updateRectP->left)
  987.     {
  988.         srcRect.left += updateRectP->left - dstRect.left;
  989.         dstRect.left = updateRectP->left;
  990.     }
  991.     
  992.     if (dstRect.right > updateRectP->right)
  993.     {
  994.         srcRect.right += updateRectP->right - dstRect.right;
  995.         dstRect.right = updateRectP->right;
  996.     }
  997.  
  998.     
  999.         // Is the sprite visible in this rect?
  1000.     if ( (dstRect.right > dstRect.left) && (dstRect.bottom > dstRect.top) )
  1001.     {
  1002.         gSWCurrentSpriteBeingDrawn = curSpriteP;
  1003.         
  1004.             // Make the sprite's rect local to the offscreen area
  1005.         tempDstRect = dstRect;
  1006.         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  1007.         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1008.         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  1009.         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  1010.         
  1011.         SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP, &srcRect, &tempDstRect);
  1012.         
  1013.         gSWCurrentSpriteBeingDrawn = NULL;
  1014.         
  1015.             // Draw tiles above sprite
  1016.         if (spriteWorldP->tilingIsOn &&
  1017.             curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  1018.         {
  1019.             SWDrawTilesAboveSprite(spriteWorldP, &dstRect, curSpriteP->tileDepth);
  1020.         }
  1021.     }        
  1022. }
  1023.  
  1024.  
  1025. #pragma mark -
  1026. ///--------------------------------------------------------------------------------------
  1027. //  SWMoveCircularVisScrollRect
  1028. ///--------------------------------------------------------------------------------------
  1029.  
  1030. SW_FUNC void SWMoveCircularVisScrollRect(
  1031.     SpriteWorldPtr    spriteWorldP,
  1032.     short            horizPos,
  1033.     short            vertPos)
  1034. {
  1035.     short    width, height, moveBoundsWidth, moveBoundsHeight;
  1036.     
  1037.     height = spriteWorldP->visScrollRect.bottom - spriteWorldP->visScrollRect.top;
  1038.     width = spriteWorldP->visScrollRect.right - spriteWorldP->visScrollRect.left;
  1039.  
  1040.     spriteWorldP->visScrollRect.top = vertPos;
  1041.     spriteWorldP->visScrollRect.bottom = vertPos + height;
  1042.     spriteWorldP->visScrollRect.left = horizPos;
  1043.     spriteWorldP->visScrollRect.right = horizPos + width;
  1044.     
  1045.     moveBoundsWidth = SW_RECT_WIDTH(spriteWorldP->scrollRectMoveBounds);
  1046.     moveBoundsHeight = SW_RECT_HEIGHT(spriteWorldP->scrollRectMoveBounds);
  1047.     
  1048.         // Wrap visScrollRect if it has moved past the circular world's moveBounds
  1049.     if (spriteWorldP->visScrollRect.top >= spriteWorldP->scrollRectMoveBounds.bottom)
  1050.     {
  1051.         spriteWorldP->visScrollRect.top -= moveBoundsHeight;
  1052.         spriteWorldP->visScrollRect.bottom -= moveBoundsHeight;
  1053.     }
  1054.     else if (spriteWorldP->visScrollRect.top < spriteWorldP->scrollRectMoveBounds.top)
  1055.     {
  1056.         spriteWorldP->visScrollRect.top += moveBoundsHeight;
  1057.         spriteWorldP->visScrollRect.bottom += moveBoundsHeight;
  1058.     }
  1059.     
  1060.     if (spriteWorldP->visScrollRect.left >= spriteWorldP->scrollRectMoveBounds.right)
  1061.     {
  1062.         spriteWorldP->visScrollRect.left -= moveBoundsWidth;
  1063.         spriteWorldP->visScrollRect.right -= moveBoundsWidth;
  1064.     }
  1065.     else if (spriteWorldP->visScrollRect.left < spriteWorldP->scrollRectMoveBounds.left)
  1066.     {
  1067.         spriteWorldP->visScrollRect.left += moveBoundsWidth;
  1068.         spriteWorldP->visScrollRect.right += moveBoundsWidth;
  1069.     }
  1070.  
  1071.     SWCalculateOffscreenScrollRect(spriteWorldP);
  1072. }
  1073.  
  1074.  
  1075. ///--------------------------------------------------------------------------------------
  1076. //  SWOffsetCircularVisScrollRect
  1077. ///--------------------------------------------------------------------------------------
  1078.  
  1079. SW_FUNC void SWOffsetCircularVisScrollRect(
  1080.     SpriteWorldPtr    spriteWorldP,
  1081.     short            horizOffset,
  1082.     short            vertOffset)
  1083. {
  1084.     short    moveBoundsWidth, moveBoundsHeight;
  1085.     
  1086.     spriteWorldP->visScrollRect.top += vertOffset;
  1087.     spriteWorldP->visScrollRect.bottom += vertOffset;
  1088.     spriteWorldP->visScrollRect.left += horizOffset;
  1089.     spriteWorldP->visScrollRect.right += horizOffset;
  1090.     
  1091.     moveBoundsWidth = SW_RECT_WIDTH(spriteWorldP->scrollRectMoveBounds);
  1092.     moveBoundsHeight = SW_RECT_HEIGHT(spriteWorldP->scrollRectMoveBounds);
  1093.  
  1094.         // Wrap visScrollRect if it has moved past the circular world's moveBounds
  1095.     if (spriteWorldP->visScrollRect.top >= spriteWorldP->scrollRectMoveBounds.bottom)
  1096.     {
  1097.         spriteWorldP->visScrollRect.top -= moveBoundsHeight;
  1098.         spriteWorldP->visScrollRect.bottom -= moveBoundsHeight;
  1099.     }
  1100.     else if (spriteWorldP->visScrollRect.top < spriteWorldP->scrollRectMoveBounds.top)
  1101.     {
  1102.         spriteWorldP->visScrollRect.top += moveBoundsHeight;
  1103.         spriteWorldP->visScrollRect.bottom += moveBoundsHeight;
  1104.     }
  1105.     
  1106.     if (spriteWorldP->visScrollRect.left >= spriteWorldP->scrollRectMoveBounds.right)
  1107.     {
  1108.         spriteWorldP->visScrollRect.left -= moveBoundsWidth;
  1109.         spriteWorldP->visScrollRect.right -= moveBoundsWidth;
  1110.     }
  1111.     else if (spriteWorldP->visScrollRect.left < spriteWorldP->scrollRectMoveBounds.left)
  1112.     {
  1113.         spriteWorldP->visScrollRect.left += moveBoundsWidth;
  1114.         spriteWorldP->visScrollRect.right += moveBoundsWidth;
  1115.     }
  1116.  
  1117.     SWCalculateOffscreenScrollRect(spriteWorldP);
  1118. }
  1119.  
  1120.  
  1121. ///--------------------------------------------------------------------------------------
  1122. //    SWCollideCircularSpriteLayer - compares wrapped srcSprite with wrapped dstSprite
  1123. ///--------------------------------------------------------------------------------------
  1124.  
  1125. SW_FUNC void SWCollideCircularSpriteLayer(
  1126.     SpriteWorldPtr spriteWorldP,
  1127.     SpriteLayerPtr srcSpriteLayerP,
  1128.     SpriteLayerPtr dstSpriteLayerP)
  1129. {
  1130.     SpritePtr    srcSpriteP, nextSrcSpriteP;
  1131.     SpritePtr    dstSpriteP, nextDstSpriteP;
  1132.     Rect        sectRect, srcRect[4], dstRect[4];
  1133.     Boolean        srcRectWrapped[4], dstRectWrapped[4];
  1134.     short        srcNum, dstNum, moveBoundsWidth, moveBoundsHeight;
  1135.     
  1136.         // Don't check for collisions unless the frame has been processed!
  1137.     if (!spriteWorldP->frameHasOccurred)
  1138.         return;
  1139.     
  1140.     moveBoundsWidth = SW_RECT_WIDTH(spriteWorldP->scrollRectMoveBounds);
  1141.     moveBoundsHeight = SW_RECT_HEIGHT(spriteWorldP->scrollRectMoveBounds);
  1142.     
  1143.     srcRectWrapped[0] = true;    // These values will always be true
  1144.     dstRectWrapped[0] = true;
  1145.  
  1146.     srcSpriteP = srcSpriteLayerP->headSpriteP;
  1147.  
  1148.         // Cycle through all source Sprites
  1149.     while (srcSpriteP != NULL)
  1150.     {
  1151.             // Skip this sprite if it has no collideProc
  1152.         if (srcSpriteP->spriteCollideProc == NULL)
  1153.         {
  1154.             srcSpriteP = srcSpriteP->nextSpriteP;
  1155.             continue;
  1156.         }
  1157.         
  1158.         dstSpriteP = dstSpriteLayerP->headSpriteP;
  1159.         nextSrcSpriteP = srcSpriteP->nextSpriteP;
  1160.         srcRect[0] = srcSpriteP->destFrameRect;
  1161.         
  1162.         //-----------------------Clip the source sprite-----------------------
  1163.         
  1164.             // Keeps track of which rects were given values
  1165.         srcRectWrapped[1] = srcRectWrapped[2] = srcRectWrapped[3] = false;
  1166.  
  1167.             // Wrap bottom piece to the top //
  1168.         if (srcRect[0].bottom > spriteWorldP->scrollRectMoveBounds.bottom)
  1169.         {
  1170.             srcRect[1].top = srcRect[0].top - moveBoundsHeight;
  1171.             srcRect[1].bottom = srcRect[0].bottom - moveBoundsHeight;
  1172.             srcRect[1].left = srcRect[0].left;
  1173.             srcRect[1].right = srcRect[0].right;
  1174.             srcRectWrapped[1] = true;
  1175.         }
  1176.         
  1177.             // Wrap right piece to the left //
  1178.         if (srcRect[0].right > spriteWorldP->scrollRectMoveBounds.right)
  1179.         {
  1180.             srcRect[2].top = srcRect[0].top;
  1181.             srcRect[2].bottom = srcRect[0].bottom;
  1182.             srcRect[2].left = srcRect[0].left - moveBoundsWidth;
  1183.             srcRect[2].right = srcRect[0].right - moveBoundsWidth;
  1184.             srcRectWrapped[2] = true;
  1185.         }
  1186.         
  1187.             // Wrap bottom-right piece to upper left corner //
  1188.         if (srcRectWrapped[1] && srcRectWrapped[2])
  1189.         {
  1190.             srcRect[3].top = srcRect[1].top;
  1191.             srcRect[3].bottom = srcRect[1].bottom;
  1192.             srcRect[3].left = srcRect[2].left;
  1193.             srcRect[3].right = srcRect[2].right;
  1194.             srcRectWrapped[3] = true;
  1195.         }
  1196.     
  1197.             // Cycle through all dest Sprites
  1198.         while (dstSpriteP != NULL)
  1199.         {
  1200.             nextDstSpriteP = dstSpriteP->nextSpriteP;
  1201.             dstRect[0] = dstSpriteP->destFrameRect;
  1202.             
  1203.             //-----------------------Clip the dest sprite-----------------------
  1204.             
  1205.             if (srcSpriteP != dstSpriteP)
  1206.             {
  1207.                     // Keeps track of which rects were given values
  1208.                 dstRectWrapped[1] = dstRectWrapped[2] = dstRectWrapped[3] = false;
  1209.  
  1210.                     // Wrap bottom piece to the top //
  1211.                 if (dstRect[0].bottom > spriteWorldP->scrollRectMoveBounds.bottom)
  1212.                 {
  1213.                     dstRect[1].top = dstRect[0].top - moveBoundsHeight;
  1214.                     dstRect[1].bottom = dstRect[0].bottom - moveBoundsHeight;
  1215.                     dstRect[1].left = dstRect[0].left;
  1216.                     dstRect[1].right = dstRect[0].right;
  1217.                     dstRectWrapped[1] = true;
  1218.                 }
  1219.                 
  1220.                     // Wrap right piece to the left //
  1221.                 if (dstRect[0].right > spriteWorldP->scrollRectMoveBounds.right)
  1222.                 {
  1223.                     dstRect[2].top = dstRect[0].top;
  1224.                     dstRect[2].bottom = dstRect[0].bottom;
  1225.                     dstRect[2].left = dstRect[0].left - moveBoundsWidth;
  1226.                     dstRect[2].right = dstRect[0].right - moveBoundsWidth;
  1227.                     dstRectWrapped[2] = true;
  1228.                 }
  1229.                 
  1230.                     // Wrap bottom-right piece to upper left corner //
  1231.                 if (dstRectWrapped[1] && dstRectWrapped[2])
  1232.                 {
  1233.                     dstRect[3].top = dstRect[1].top;
  1234.                     dstRect[3].bottom = dstRect[1].bottom;
  1235.                     dstRect[3].left = dstRect[2].left;
  1236.                     dstRect[3].right = dstRect[2].right;
  1237.                     dstRectWrapped[3] = true;
  1238.                 }
  1239.             
  1240.  
  1241.                     // Check for overlapping rects (compare each dstRect with each srcRect)
  1242.                 for (srcNum = 0; srcNum <= 3; srcNum++)
  1243.                 {
  1244.                     if (srcRectWrapped[srcNum] == false)
  1245.                         continue;
  1246.                     
  1247.                     for (dstNum = 0; dstNum <= 3; dstNum++)
  1248.                     {
  1249.                         if (dstRectWrapped[dstNum] == false)
  1250.                             continue;
  1251.  
  1252.                         if ( (srcRect[srcNum].top < dstRect[dstNum].bottom) && 
  1253.                              (srcRect[srcNum].bottom > dstRect[dstNum].top) &&
  1254.                              (srcRect[srcNum].left < dstRect[dstNum].right) && 
  1255.                              (srcRect[srcNum].right > dstRect[dstNum].left) )
  1256.                         {
  1257.                             sectRect.left = SW_MAX(srcRect[srcNum].left, dstRect[dstNum].left);
  1258.                             sectRect.top = SW_MAX(srcRect[srcNum].top, dstRect[dstNum].top);
  1259.                             sectRect.right = SW_MIN(srcRect[srcNum].right, dstRect[dstNum].right);
  1260.                             sectRect.bottom = SW_MIN(srcRect[srcNum].bottom, dstRect[dstNum].bottom);
  1261.  
  1262.                             (*srcSpriteP->spriteCollideProc)(srcSpriteP, dstSpriteP, §Rect);
  1263.                         }
  1264.                     }
  1265.                 }
  1266.             }
  1267.             
  1268.                 // If the nextDstSpriteP has been removed, we must start over again
  1269.             if (nextDstSpriteP != NULL && nextDstSpriteP->spriteRemoval != kSWDontRemoveSprite)
  1270.                 dstSpriteP = dstSpriteLayerP->headSpriteP;
  1271.             else
  1272.                 dstSpriteP = nextDstSpriteP;
  1273.         }
  1274.         
  1275.             // If the nextSrcSpriteP has been removed, we must start over again
  1276.         if (nextSrcSpriteP != NULL && nextSrcSpriteP->spriteRemoval != kSWDontRemoveSprite)
  1277.             srcSpriteP = srcSpriteLayerP->headSpriteP;
  1278.         else
  1279.             srcSpriteP = nextSrcSpriteP;
  1280.     }
  1281. }
  1282.  
  1283.  
  1284. ///--------------------------------------------------------------------------------------
  1285. //    SWChangeCircularTileImage - this function simply calls SWUpdateCircularTileOnScreen
  1286. ///--------------------------------------------------------------------------------------
  1287.  
  1288. SW_FUNC void SWChangeCircularTileImage(
  1289.     SpriteWorldPtr    spriteWorldP,
  1290.     short            tileID,
  1291.     short            newImage)
  1292. {
  1293.         // Set the current image
  1294.     spriteWorldP->curTileImage[tileID] = newImage;
  1295.     
  1296.         // Update the tile image on screen
  1297.     SWUpdateCircularTileOnScreen(spriteWorldP, tileID);
  1298. }
  1299.  
  1300.  
  1301. ///--------------------------------------------------------------------------------------
  1302. //    SWUpdateCircularTileOnScreen - this is actually quite similar to SWDrawCircularTile,
  1303. //    except that it calls SWUpdateTileOnScreen instead of SWDrawTile.
  1304. ///--------------------------------------------------------------------------------------
  1305.  
  1306. SW_FUNC void SWUpdateCircularTileOnScreen(
  1307.     SpriteWorldPtr    spriteWorldP,
  1308.     short            tileID)
  1309. {
  1310.     short        oldHorizScrollRectOffset, oldVertScrollRectOffset;
  1311.     Rect        oldVisScrollRect, rectA, rectB, rectC, rectD;
  1312.     Boolean        horizClip, vertClip;
  1313.  
  1314.     oldVisScrollRect = spriteWorldP->visScrollRect;
  1315.     oldHorizScrollRectOffset = spriteWorldP->horizScrollRectOffset;
  1316.     oldVertScrollRectOffset = spriteWorldP->vertScrollRectOffset;
  1317.     
  1318.     rectA = spriteWorldP->visScrollRect;
  1319.     
  1320.     
  1321.         // Wrap right side to the left
  1322.     if (rectA.right > spriteWorldP->scrollRectMoveBounds.right)
  1323.     {
  1324.         rectB.top = rectA.top;
  1325.         rectB.bottom = rectA.bottom;
  1326.         rectB.left = spriteWorldP->scrollRectMoveBounds.left;
  1327.         rectB.right = rectA.right - spriteWorldP->scrollRectMoveBounds.right;
  1328.         
  1329.         rectA.right = spriteWorldP->scrollRectMoveBounds.right;
  1330.         horizClip = true;
  1331.     }
  1332.     else
  1333.         horizClip = false;
  1334.     
  1335.     
  1336.         // Wrap bottom side to the top
  1337.     if (rectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
  1338.     {
  1339.         rectC.left = rectA.left;
  1340.         rectC.right = rectA.right;
  1341.         rectC.top = spriteWorldP->scrollRectMoveBounds.top;
  1342.         rectC.bottom = rectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
  1343.         
  1344.         rectA.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  1345.         rectB.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  1346.         vertClip = true;
  1347.     }
  1348.     else
  1349.         vertClip = false;
  1350.     
  1351.     
  1352.         // Update tiles in rectA
  1353.     spriteWorldP->visScrollRect = rectA;
  1354.     SWUpdateTileOnScreen(spriteWorldP, tileID);
  1355.         
  1356.     
  1357.         // Update tiles in rectB
  1358.     if (horizClip)
  1359.     {
  1360.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the tile at the left of the world
  1361.         
  1362.         spriteWorldP->visScrollRect = rectB;
  1363.         SWUpdateTileOnScreen(spriteWorldP, tileID);
  1364.         
  1365.         spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
  1366.     }
  1367.     
  1368.         // Update tiles in rectC
  1369.     if (vertClip)
  1370.     {
  1371.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the tile at the top of the world
  1372.  
  1373.         spriteWorldP->visScrollRect = rectC;
  1374.         SWUpdateTileOnScreen(spriteWorldP, tileID);
  1375.         
  1376.         spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
  1377.     }
  1378.     
  1379.         // Update tiles in rectD (corner piece)
  1380.     if (vertClip && horizClip)
  1381.     {
  1382.         rectD.left = rectB.left;
  1383.         rectD.right = rectB.right;
  1384.         rectD.top = rectC.top;
  1385.         rectD.bottom = rectC.bottom;
  1386.         
  1387.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the sprites at the left of the world
  1388.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the sprites at the top of the world
  1389.         
  1390.         spriteWorldP->visScrollRect = rectD;
  1391.         SWUpdateTileOnScreen(spriteWorldP, tileID);
  1392.         
  1393.         spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
  1394.         spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
  1395.     }
  1396.     
  1397.     
  1398.         // Restore visScrollRect now that we're done
  1399.     spriteWorldP->visScrollRect = oldVisScrollRect;
  1400. }
  1401.  
  1402.  
  1403. ///--------------------------------------------------------------------------------------
  1404. //    SWDrawTilesInCircularBackground
  1405. ///--------------------------------------------------------------------------------------
  1406.  
  1407. SW_FUNC OSErr SWDrawTilesInCircularBackground(
  1408.     SpriteWorldPtr    spriteWorldP)
  1409. {
  1410.     short        oldHorizScrollRectOffset, oldVertScrollRectOffset;
  1411.     Rect        oldVisScrollRect, rectA, rectB, rectC, rectD;
  1412.     Boolean        horizClip, vertClip;
  1413.     GWorldPtr    holdGWorld;
  1414.     GDHandle    holdGDH;
  1415.     
  1416.     GetGWorld( &holdGWorld, &holdGDH );
  1417.     
  1418.     if ( !spriteWorldP->tilingIsInitialized )
  1419.     {
  1420.         SWSetStickyIfError(kTilingNotInitialized);
  1421.         return kTilingNotInitialized;
  1422.     }
  1423.  
  1424.     
  1425.         // Save these values so we can restore them later
  1426.     oldVisScrollRect = spriteWorldP->visScrollRect;
  1427.     oldHorizScrollRectOffset = spriteWorldP->horizScrollRectOffset;
  1428.     oldVertScrollRectOffset = spriteWorldP->vertScrollRectOffset;
  1429.     
  1430.     rectA = spriteWorldP->visScrollRect;
  1431.     
  1432.     
  1433.         // Wrap right side to the left
  1434.     if (rectA.right > spriteWorldP->scrollRectMoveBounds.right)
  1435.     {
  1436.         rectB.top = rectA.top;
  1437.         rectB.bottom = rectA.bottom;
  1438.         rectB.left = spriteWorldP->scrollRectMoveBounds.left;
  1439.         rectB.right = rectA.right - spriteWorldP->scrollRectMoveBounds.right;
  1440.         
  1441.         rectA.right = spriteWorldP->scrollRectMoveBounds.right;
  1442.         horizClip = true;
  1443.     }
  1444.     else
  1445.         horizClip = false;
  1446.     
  1447.     
  1448.         // Wrap bottom side to the top
  1449.     if (rectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
  1450.     {
  1451.         rectC.left = rectA.left;
  1452.         rectC.right = rectA.right;
  1453.         rectC.top = spriteWorldP->scrollRectMoveBounds.top;
  1454.         rectC.bottom = rectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
  1455.         
  1456.         rectA.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  1457.         rectB.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  1458.         vertClip = true;
  1459.     }
  1460.     else
  1461.         vertClip = false;
  1462.     
  1463.     
  1464.         // Draw tiles in the main piece
  1465.     spriteWorldP->visScrollRect = rectA;
  1466.     (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectA, true);
  1467.     
  1468.     
  1469.         // Draw tile in rectB
  1470.     if (horizClip)
  1471.     {
  1472.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the tiles at the left of the world
  1473.         
  1474.         spriteWorldP->visScrollRect = rectB;
  1475.         (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectB, false);
  1476.         
  1477.         spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
  1478.     }
  1479.     
  1480.         // Draw tile in rectC
  1481.     if (vertClip)
  1482.     {
  1483.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the tiles at the top of the world
  1484.         
  1485.         spriteWorldP->visScrollRect = rectC;
  1486.         (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectC, false);
  1487.         
  1488.         spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
  1489.     }
  1490.     
  1491.         // Draw tile in rectD (corner piece)
  1492.     if (vertClip && horizClip)
  1493.     {
  1494.         rectD.left = rectB.left;
  1495.         rectD.right = rectB.right;
  1496.         rectD.top = rectC.top;
  1497.         rectD.bottom = rectC.bottom;
  1498.         
  1499.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the sprites at the left of the world
  1500.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the sprites at the top of the world
  1501.         
  1502.         spriteWorldP->visScrollRect = rectD;
  1503.         (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectD, false);
  1504.         
  1505.         spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
  1506.         spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
  1507.     }
  1508.     
  1509.         // Restore visScrollRect now that we're done
  1510.     spriteWorldP->visScrollRect = oldVisScrollRect;
  1511.     
  1512.     
  1513.         // Restore the original port
  1514.     SetGWorld( holdGWorld, holdGDH );
  1515.     
  1516.     return noErr;
  1517. }
  1518.  
  1519.  
  1520. ///--------------------------------------------------------------------------------------
  1521. //    SWDrawCircularTile
  1522. ///--------------------------------------------------------------------------------------
  1523.  
  1524. SW_FUNC void SWDrawCircularTile(
  1525.     SpriteWorldPtr    spriteWorldP,
  1526.     short            dstTileLayer,
  1527.     short            tileRow,
  1528.     short            tileCol,
  1529.     short            tileID)
  1530. {
  1531.     short        oldHorizScrollRectOffset, oldVertScrollRectOffset;
  1532.     Rect        tileRect, oldVisScrollRect, rectA, rectB, rectC, rectD;
  1533.     Boolean        horizClip, vertClip;
  1534.     
  1535.         // We must have a TileMap installed in the dstTileLayer to draw in it!
  1536.     if (spriteWorldP->tileLayerArray[dstTileLayer] == NULL)
  1537.         return;
  1538.     
  1539.     tileRect.top = tileRow * spriteWorldP->tileHeight;
  1540.     tileRect.left = tileCol * spriteWorldP->tileWidth;
  1541.     tileRect.bottom = tileRect.top + spriteWorldP->tileHeight;
  1542.     tileRect.right = tileRect.left + spriteWorldP->tileWidth;
  1543.  
  1544.         // Save these values so we can restore them later
  1545.     oldVisScrollRect = spriteWorldP->visScrollRect;
  1546.     oldHorizScrollRectOffset = spriteWorldP->horizScrollRectOffset;
  1547.     oldVertScrollRectOffset = spriteWorldP->vertScrollRectOffset;
  1548.     
  1549.     rectA = spriteWorldP->visScrollRect;
  1550.     
  1551.     
  1552.         // Wrap right side to the left
  1553.     if (rectA.right > spriteWorldP->scrollRectMoveBounds.right)
  1554.     {
  1555.         rectB.top = rectA.top;
  1556.         rectB.bottom = rectA.bottom;
  1557.         rectB.left = spriteWorldP->scrollRectMoveBounds.left;
  1558.         rectB.right = rectA.right - spriteWorldP->scrollRectMoveBounds.right;
  1559.         
  1560.         rectA.right = spriteWorldP->scrollRectMoveBounds.right;
  1561.         horizClip = true;
  1562.     }
  1563.     else
  1564.         horizClip = false;
  1565.     
  1566.     
  1567.         // Wrap bottom side to the top
  1568.     if (rectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
  1569.     {
  1570.         rectC.left = rectA.left;
  1571.         rectC.right = rectA.right;
  1572.         rectC.top = spriteWorldP->scrollRectMoveBounds.top;
  1573.         rectC.bottom = rectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
  1574.         
  1575.         rectA.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  1576.         rectB.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  1577.         vertClip = true;
  1578.     }
  1579.     else
  1580.         vertClip = false;
  1581.     
  1582.     
  1583.         // Draw tile in rectA
  1584.     if ( SW_RECT_IS_IN_RECT(tileRect, rectA) )
  1585.     {
  1586.         spriteWorldP->visScrollRect = rectA;
  1587.         SWDrawTile(spriteWorldP, dstTileLayer, tileRow, tileCol, tileID);
  1588.     }
  1589.     
  1590.         // Draw tile in rectB
  1591.     if (horizClip)
  1592.     {
  1593.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the tile at the left of the world
  1594.         
  1595.         if ( SW_RECT_IS_IN_RECT(tileRect, rectB) )
  1596.         {
  1597.             spriteWorldP->visScrollRect = rectB;
  1598.             SWDrawTile(spriteWorldP, dstTileLayer, tileRow, tileCol, tileID);
  1599.         }
  1600.         
  1601.         spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
  1602.     }
  1603.     
  1604.         // Draw tile in rectC
  1605.     if (vertClip)
  1606.     {
  1607.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the tile at the top of the world
  1608.         
  1609.         if ( SW_RECT_IS_IN_RECT(tileRect, rectC) )
  1610.         {
  1611.             spriteWorldP->visScrollRect = rectC;
  1612.             SWDrawTile(spriteWorldP, dstTileLayer, tileRow, tileCol, tileID);
  1613.         }
  1614.         
  1615.         spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
  1616.     }
  1617.     
  1618.         // Draw tile in rectD (corner piece)
  1619.     if (vertClip && horizClip)
  1620.     {
  1621.         rectD.left = rectB.left;
  1622.         rectD.right = rectB.right;
  1623.         rectD.top = rectC.top;
  1624.         rectD.bottom = rectC.bottom;
  1625.         
  1626.         spriteWorldP->horizScrollRectOffset = 0;  // Draw the sprites at the left of the world
  1627.         spriteWorldP->vertScrollRectOffset = 0;  // Draw the sprites at the top of the world
  1628.         
  1629.         if ( SW_RECT_IS_IN_RECT(tileRect, rectD) )
  1630.         {
  1631.             spriteWorldP->visScrollRect = rectD;
  1632.             SWDrawTile(spriteWorldP, dstTileLayer, tileRow, tileCol, tileID);
  1633.         }
  1634.         
  1635.         spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
  1636.         spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
  1637.     }
  1638.     
  1639.         // Put the new tileID in the TileMap (done in case the tile isn't visible in
  1640.         // any part of the visScrollRect, in which case SWDrawTile would never be called.)
  1641.     spriteWorldP->tileLayerArray[dstTileLayer]->tileMap[tileRow][tileCol] = tileID;
  1642.     
  1643.         // Restore visScrollRect now that we're done
  1644.     spriteWorldP->visScrollRect = oldVisScrollRect;
  1645. }
  1646.  
  1647.